package com.bbcare.cp.plat.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.bbcare.comm.AppException;
import com.bbcare.comm.ConstantParams;
import com.bbcare.comm.Constants;
import com.bbcare.comm.ErrorCode;
import com.bbcare.comm.ToolUtil;
import com.bbcare.cp.plat.entity.cp.ContentTempl;
import com.bbcare.cp.plat.entity.cp.ContentTemplVersion;
import com.bbcare.cp.plat.entity.cp.CpNodeAuth;
import com.bbcare.cp.plat.entity.cp.CpNodeTask;
import com.bbcare.cp.plat.entity.cp.CpNodeTaskAuth;
import com.bbcare.cp.plat.entity.cp.CpNodeTaskCont;
import com.bbcare.cp.plat.entity.cp.CpScheme;
import com.bbcare.cp.plat.entity.cp.CpSchemeNode;
import com.bbcare.cp.plat.entity.cp.CpSchemeStage;
import com.bbcare.cp.plat.entity.cp.CpSchemeVersion;
import com.bbcare.cp.plat.service.IContTemplService;
import com.bbcare.cp.plat.service.ICpSchemeTemplService;
import com.bbcare.cp.plat.store.ibatis.cp.ICpNodeTaskDAO;
import com.bbcare.cp.plat.store.ibatis.cp.ICpSchemeDAO;
import com.bbcare.cp.plat.store.ibatis.cp.ICpSchemeNodeDAO;
import com.bbcare.cp.plat.store.ibatis.cp.ICpSchemeStageDAO;
import com.bbcare.cp.plat.store.ibatis.cp.ICpTaskContDAO;
import com.bbcare.cp.plat.util.ConfCacheUtil;

/**
 * @name: 临床路径方案接口实现（通用接口独立出来）
 * @author: DemonLee
 * @createTime: 2018.4.20
 * @description: 临床路径方案及内容等相关的操作
 * @modify:
 *
 */
@Service
public class CpSchemeTemplServiceImpl implements ICpSchemeTemplService {
    private final Log logger = LogFactory.getLog(CpSchemeTemplServiceImpl.class);

    @Autowired
    private ICpSchemeDAO cpSchemeDao;

    @Autowired
    private ICpSchemeStageDAO cpSchemeStageDao;

    @Autowired
    private ICpSchemeNodeDAO cpSchemeNodeDao;

    @Autowired
    private ICpNodeTaskDAO cpNodeTaskDao;

    @Autowired
    private ICpTaskContDAO cpTaskContDao;

    @Autowired
    private IContTemplService contTemplService;

    // 根据临床路径id查询建档内容接口实现
    @Override
    public Map<String, Object> querySchemeArchive(Map<String, Object> argMap) throws Exception {
        logger.debug("---querySchemeArchive---argMap==" + argMap);
        Map<String, Object> outMap = new HashMap<String, Object>();
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeId = (String) mapIn.get("schemeId");
        String projectRoleId = (String) mapIn.get("projectRoleId");

        Map<String, Object> qryMap = new HashMap<String, Object>();
        Map<String, Object> qryOut = new HashMap<String, Object>();
        // step1: 查询当前方案版本
        qryMap.put("schemeId", schemeId);
        qryOut = this.querySchemeAndVersion(qryMap);
        if (MapUtils.isEmpty(qryOut)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_NOT_EXISTS, "查询临床路径方案记录不存在，请核实配置信息！"));
        }
        CpSchemeVersion cpsv = (CpSchemeVersion) qryOut.get("cpSchemeVersion");

        // step2: 查询方案下第一个阶段及阶段下第一个节点
        String schemeVersionId = cpsv.getId();
        qryMap.clear();
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("projectRoleId", projectRoleId);
        qryMap.put("stageSeqNo", Constants.CP_SEQ_FOR_INIT);
        qryMap.put("nodeSeqNo", Constants.CP_SEQ_FOR_INIT);
        Map<String, Object> stageNodeOut = this.querySchemeStageAndNode(qryMap);
        if (MapUtils.isEmpty(stageNodeOut)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_STAGE_NOT_EXISTS, "临床路径方案下阶段信息不存在，请核实配置信息！"));
        }
        List<Object> stageList = ToolUtil.typeCast(stageNodeOut.get("stageList"));
        if (CollectionUtils.isEmpty(stageList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_STAGE_NOT_EXISTS, "临床路径方案下阶段信息不存在，请核实配置信息！"));
        }
        Map<String, Object> stageInfo = ToolUtil.typeCast(stageList.get(0));
        List<CpSchemeNode> nodeList = ToolUtil.typeCast(stageInfo.get("nodeList"));
        if (CollectionUtils.isEmpty(nodeList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_NODE_NOT_EXISTS, "临床路径阶段下节点信息不存在，请核实配置信息！"));
        }
        CpSchemeStage cssVo = (CpSchemeStage) stageInfo.get("stageInfo");
        CpSchemeNode csnVo = nodeList.get(0);

        // step3: 查询建档节点下的任务及任务内容
        qryMap.clear();
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("projectRoleId", projectRoleId);
        qryMap.put("nodeId", csnVo.getId());

        Map<String, Object> taskContOut = this.queryCpSchemeNodeTask(qryMap);
        List<CpNodeTask> nodeTaskList = ToolUtil.typeCast(taskContOut.get("nodeTaskList"));
        if (CollectionUtils.isEmpty(nodeTaskList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPNODE_TASK_NOT_EXISTS, "临床路径建档节点下任务信息不存在，请核实配置信息！"));
        }
        outMap.put("taskList", nodeTaskList);
        outMap.put("taskSize", nodeTaskList.size());
        outMap.put("schemeVersionId", schemeVersionId);
        outMap.put("nodeId", csnVo.getId());
        outMap.put("stageId", cssVo.getId());

        return outMap;
    }

    // 根据临床路径id查询对应角色下该方案下所有阶段、节点等
    @Override
    public Map<String, Object> querySchemeStageNode(Map<String, Object> argMap) throws Exception {
        logger.debug("---querySchemeStageNode---argMap==" + argMap);
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeId = (String) mapIn.get("schemeId");
        String projectRoleId = (String) mapIn.get("projectRoleId");
        Integer InsFlag = (Integer) mapIn.get("InsFlag");
        // 节点类型
        String nodeType = (String) mapIn.get("nodeType");

        Map<String, Object> qryMap = new HashMap<String, Object>();
        Map<String, Object> qryOut = new HashMap<String, Object>();
        // step1: 查询当前方案版本
        qryMap.put("schemeId", schemeId);
        qryOut = this.querySchemeAndVersion(qryMap);
        if (MapUtils.isEmpty(qryOut)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_NOT_EXISTS, "查询临床路径方案记录不存在，请核实配置信息！"));
        }
        CpSchemeVersion cpsv = (CpSchemeVersion) qryOut.get("cpSchemeVersion");

        // step2: 查询方案下阶段及阶段下节点
        Map<String, Object> outMap = null;
        String schemeVersionId = cpsv.getId();
        qryMap.clear();
        if (null != InsFlag) {
            // 查询哪些节点
            if (ConstantParams.CP_SCHEME_INS_FLAG_0 == InsFlag) {
                // 只查询建档阶段下节点
                qryMap.put("stageSeqNo", Constants.CP_SEQ_FOR_INIT);
            } else if (ConstantParams.CP_SCHEME_INS_FLAG_1 == InsFlag) {
                // 查询建档阶段下节点以外的其他所有节点
                qryMap.put("revStageSeqNo", Constants.CP_SEQ_FOR_INIT);
            } else if (ConstantParams.CP_SCHEME_INS_FLAG_2 == InsFlag) {
                // 查询所有节点
            }
        }
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("projectRoleId", projectRoleId);
        qryMap.put("nodeType", nodeType);
        if (StringUtils.isNotBlank(projectRoleId)) {
            // 关联角色
            outMap = this.querySchemeStageAndNode(qryMap);
        } else {
            // 不关联角色
            outMap = this.querySchemeStageNodeNoRole(qryMap);
        }
        if (MapUtils.isEmpty(outMap)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_STAGE_NOT_EXISTS, "临床路径方案下阶段信息不存在，请核实配置信息！"));
        }
        List<Object> stageList = ToolUtil.typeCast(outMap.get("stageList"));
        if (CollectionUtils.isEmpty(stageList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_STAGE_NOT_EXISTS, "临床路径方案下阶段信息不存在，请核实配置信息！"));
        }
        outMap.put("CpScheme", qryOut.get("cpScheme"));
        outMap.put("CpSchemeVersion", cpsv);

        return outMap;
    }

    // 根据临床路径id查询临床路径及版本信息接口实现
    @Override
    public Map<String, Object> querySchemeAndVersion(Map<String, Object> argMap) throws Exception {
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeId = (String) mapIn.get("schemeId");
        if (StringUtils.isBlank(schemeId)) {
            return null;
        }
        String isGetData = MapUtils.getString(mapIn, "isGetData");

        // step1: 查询临床路径信息
        Map<String, Object> qryMap = new HashMap<String, Object>();
        qryMap.put("id", schemeId);
        List<CpScheme> cpsList = cpSchemeDao.listCpSchemeByCondition(qryMap);
        if (CollectionUtils.isEmpty(cpsList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_NOT_EXISTS, "查询临床路径方案记录不存在，请核实配置信息！"));
        }
        CpScheme cpsVo = cpsList.get(0);
        String cpsStatus = cpsVo.getStatus();
        if (StringUtils.isNotBlank(cpsStatus) && Constants.SCHEME_STATUS_DELETE.equals(cpsStatus)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_HAS_REMOVED, "该临床路径方案已被删除，无法使用！"));
        }

        // step2: 查询临床路径版本信息（草稿状态版本号还是旧版本号，故不需要特殊处理）
        List<CpSchemeVersion> cpsvList = null;
        qryMap.clear();
        qryMap.put("schemeId", schemeId);
        qryMap.put("schemeVersion", cpsVo.getNewVersion());
        qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        if ("Y".equals(isGetData)) {
            // 查询内容详情
            cpsvList = cpSchemeDao.listCpSchemeVersionDataByScheme(qryMap);
        } else {
            // 不查询内容详情
            cpsvList = cpSchemeDao.listCpSchemeVersionByCondition(qryMap);
        }
        if (CollectionUtils.isEmpty(cpsvList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEMEVERSION_NOT_EXISTS, "临床路径方案版本记录不存在，请核实配置信息！"));
        }

        Map<String, Object> outMap = new HashMap<String, Object>();
        outMap.put("cpScheme", cpsVo);
        outMap.put("cpSchemeVersion", cpsvList.get(0));

        return outMap;
    }

    // 临床路径阶段及阶段下节点查询接口实现（关联角色）
    @Override
    public Map<String, Object> querySchemeStageAndNode(Map<String, Object> argMap) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeVersionId = (String) mapIn.get("schemeVersionId");
        String projectRoleId = (String) mapIn.get("projectRoleId");
        // 序号可能为空
        Integer stageSeqNo = (Integer) mapIn.get("stageSeqNo");
        Integer nodeSeqNo = (Integer) mapIn.get("nodeSeqNo");
        Integer revNodeSeqNo = (Integer) mapIn.get("revNodeSeqNo");
        Integer revStageSeqNo = (Integer) mapIn.get("revStageSeqNo");
        // 节点类型
        String nodeType = (String) mapIn.get("nodeType");

        // step1: 查询路径阶段
        Map<String, Object> qryMap = new HashMap<String, Object>();
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("seqNo", stageSeqNo);
        qryMap.put("revSeqNo", revStageSeqNo);
        qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        List<CpSchemeStage> cpssList = cpSchemeStageDao.listSchemeStageByCondition(qryMap);
        if (CollectionUtils.isEmpty(cpssList)) {
            return null;
        }

        // step2: 查询每个阶段下的节点
        List<Object> stageList = new ArrayList<Object>();
        qryMap.put("seqNo", nodeSeqNo);
        qryMap.put("revSeqNo", revNodeSeqNo);
        qryMap.put("nodeType", nodeType);
        CpSchemeStage cpssVo = null;
        int c = 0;
        int csize = cpssList.size();
        for (c = 0; c < csize; c++) {
            Map<String, Object> stageMap = new HashMap<String, Object>();
            cpssVo = cpssList.get(c);
            stageMap.put("stageInfo", cpssVo);

            qryMap.put("projectRoleId", projectRoleId);
            qryMap.put("stageId", cpssVo.getId());
            List<CpSchemeNode> cpnList = cpSchemeNodeDao.listCpSchemeNodeByRole(qryMap);
            // 可能返回为空
            stageMap.put("nodeList", cpnList);

            stageList.add(stageMap);
        }
        outMap.put("stageList", stageList);

        return outMap;
    }

    // 临床路径阶段及阶段下节点查询接口实现（不关联角色）
    @Override
    public Map<String, Object> querySchemeStageNodeNoRole(Map<String, Object> argMap) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeVersionId = (String) mapIn.get("schemeVersionId");
        // 序号可能为空
        Integer stageSeqNo = (Integer) mapIn.get("stageSeqNo");
        Integer nodeSeqNo = (Integer) mapIn.get("nodeSeqNo");
        Integer revNodeSeqNo = (Integer) mapIn.get("revNodeSeqNo");
        Integer revStageSeqNo = (Integer) mapIn.get("revStageSeqNo");
        // 节点类型
        String nodeType = (String) mapIn.get("nodeType");

        // step1: 查询路径阶段
        Map<String, Object> qryMap = new HashMap<String, Object>();
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("seqNo", stageSeqNo);
        qryMap.put("revSeqNo", revStageSeqNo);
        qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        List<CpSchemeStage> cpssList = cpSchemeStageDao.listSchemeStageByCondition(qryMap);
        if (CollectionUtils.isEmpty(cpssList)) {
            return null;
        }

        // step2: 查询每个阶段下的节点
        List<Object> stageList = new ArrayList<Object>();
        qryMap.put("seqNo", nodeSeqNo);
        qryMap.put("revSeqNo", revNodeSeqNo);
        qryMap.put("nodeType", nodeType);
        CpSchemeStage cpssVo = null;
        int c = 0;
        int csize = cpssList.size();
        for (c = 0; c < csize; c++) {
            Map<String, Object> stageMap = new HashMap<String, Object>();
            cpssVo = cpssList.get(c);
            stageMap.put("stageInfo", cpssVo);

            qryMap.put("stageId", cpssVo.getId());
            List<CpSchemeNode> cpnList = cpSchemeNodeDao.listCpSchemeNodeByCondition(qryMap);
            // 可能返回为空
            stageMap.put("nodeList", cpnList);

            stageList.add(stageMap);
        }
        outMap.put("stageList", stageList);

        return outMap;
    }

    // 临床路径节点下的任务查询接口实现（关联角色）
    @Override
    public Map<String, Object> queryCpSchemeNodeTask(Map<String, Object> argMap) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeVersionId = (String) mapIn.get("schemeVersionId");
        String projectRoleId = (String) mapIn.get("projectRoleId");
        String nodeId = (String) mapIn.get("nodeId");
        String taskId = (String) mapIn.get("taskId");

        // 查询节点下的任务
        Map<String, Object> qryMap = new HashMap<String, Object>();
        qryMap.put("id", taskId);
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("projectRoleId", projectRoleId);
        qryMap.put("nodeId", nodeId);
        qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);

        // 如果传入序号 则按序号查询 (建档任务查询节点下为序号为0的任务)
        qryMap.put("seqNo", mapIn.get("seqNo"));
        // 无记录的情况，通用接口不抛异常，业务调用侧判断是否需要抛
        List<CpNodeTask> nodeTaskList = cpNodeTaskDao.listCpNodeTaskByRole(qryMap);
        outMap.put("nodeTaskList", nodeTaskList);

        return outMap;
    }

    // 临床路径节点下的任务查询接口实现（不关联角色）
    @Override
    public List<CpNodeTask> listCpSchemeNodeTask(Map<String, Object> argMap) throws Exception {
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeVersionId = (String) mapIn.get("schemeVersionId");
        String nodeId = (String) mapIn.get("nodeId");
        String taskId = (String) mapIn.get("taskId");

        // 查询节点下的任务
        Map<String, Object> qryMap = new HashMap<String, Object>();
        qryMap.put("id", taskId);
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("nodeId", nodeId);
        qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);

        // 如果传入序号 则按序号查询 (建档任务查询节点下为序号为0的任务)
        qryMap.put("seqNo", mapIn.get("seqNo"));
        // 无记录的情况，通用接口不抛异常，业务调用侧判断是否需要抛
        List<CpNodeTask> nodeTaskList = cpNodeTaskDao.listCpNodeTaskByCondition(qryMap);

        return nodeTaskList;
    }

    // 根据临床路径id和角色id 查询建档任务模板内容并返回
    @Override
    public Map<String, Object> querySchemeArchiveContTempl(Map<String, Object> argMap) throws Exception {
        logger.debug("---querySchemeArchiveContTempl---argMap==" + argMap);

        Map<String, Object> outMap = new HashMap<String, Object>();
        Map<String, Object> archiveTaskMap = this.querySchemeArchive(argMap); //
        // 以下参数 上面方法已经校验
        String schemeVersionId = (String) archiveTaskMap.get("schemeVersionId");
        List<CpNodeTask> nodeTaskList = ToolUtil.typeCast(archiveTaskMap.get("taskList"));

        List<Object> outList = new ArrayList<Object>();
        for (int i = 0, k = nodeTaskList.size(); i < k; i++) {// 建档任务只有一个
            String taskId = nodeTaskList.get(i).getId();
            String taskTemplType = nodeTaskList.get(i).getTemplType();

            Map<String, Object> qryMap = new HashMap<String, Object>();
            qryMap.put("taskId", taskId);
            qryMap.put("schemeVersionId", schemeVersionId);
            qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
            List<CpNodeTaskCont> cntcList = cpTaskContDao.listCpTaskContByCondition(qryMap);
            if (CollectionUtils.isEmpty(cntcList)) {
                // 只要有一个任务内容 就返回
                continue;
                // throw (new
                // AppException(ErrorCode.CPQUEUE_EXCEPTION_CPNODE_TASKCONT_NOT_EXISTS,
                // "该任务下未配置内容模板，请核实配置信息！"));
            }

            // 返回taskId 和 路径版本id
            outMap.put("taskId", taskId);
            outMap.put("schemeVersionId", schemeVersionId);

            // step3: 循环获取每个内容模板（通用接口）
            qryMap.clear();
            qryMap.put("schemeVersionId", schemeVersionId);
            String tmplId = "";
            Integer templVersion = null;
            int c = 0;
            int csize = cntcList.size();
            logger.debug("---csize==" + csize + ", taskTemplType==" + taskTemplType);
            if (ConstantParams.CP_NODE_TASK_TEMPL_TYPE_FOR_JSON.equals(taskTemplType)) {
                // json问卷
                for (c = 0; c < csize; c++) {
                    CpNodeTaskCont cntcVo = cntcList.get(c);
                    tmplId = cntcVo.getTemplId();
                    templVersion = cntcVo.getTemplVersion();
                    qryMap.put("tmplId", tmplId);
                    qryMap.put("templVersion", templVersion);
                    Map<String, Object> contMap = contTemplService.queryContTempl(qryMap);
                    if (MapUtils.isNotEmpty(contMap)) {
                        contMap.put("contName", cntcVo.getContName());
                        contMap.put("contId", cntcVo.getId());
                        outList.add(contMap);
                    }
                }
            }
        }

        // step4: 获取结果并返回
        if (CollectionUtils.isEmpty(outList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPNODE_TASKCONT_NOT_EXISTS, "查询该任务下的内容模板为空，请核实配置信息！"));
        }
        outMap.put("schemeId", argMap.get("schemeId"));
        outMap.put("templContent", outList);

        return outMap;
    }

    /**
     * @name: 临床路径临时随访节点模板查询
     * @author: DemonLee
     * @createTime: 2018.6.14
     * @param: 方案版本id等
     * @return:
     * @modify:
     * @description:
     */
    @Override
    public Map<String, Object> querySchemeTempNode(Map<String, Object> mapIn) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();

        Map<String, Object> qryMap = new HashMap<String, Object>(mapIn);
        qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        List<CpSchemeNode> cpnRoleList = cpSchemeNodeDao.listCpSchemeNodeByRole(qryMap);
        if (CollectionUtils.isNotEmpty(cpnRoleList)) {
            // 当前角色可以看到该节点，则再查询对应节点
            String nodeId = cpnRoleList.get(0).getId();

            // 暂时临时节点只配置一个
            qryMap.put("nodeId", nodeId);
            List<CpSchemeNode> cpnList = cpSchemeNodeDao.listCpSchemeNodeByCondition(qryMap);
            outMap.put("cpNodeList", cpnList);

            qryMap.clear();
            qryMap.put("nodeId", nodeId);
            qryMap.put("schemeVersionId", mapIn.get("schemeVersionId"));
            qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
            List<CpNodeAuth> authList = cpSchemeNodeDao.listCpNodeAuthByCondition(qryMap);
            outMap.put("cpNodeAuthList", authList);
        }

        return outMap;
    }

    /**
     * @name: 根据临床路径id获取路径内容详情（含缓存刷新等）
     * @author: DemonLee
     * @createTime: 2018.6.25
     * @description: 事务在调用侧控制
     * @modify:
     *
     */
    @Override
    public Map<String, Object> dealSchemeStageNode(Map<String, Object> argMap) throws Exception {
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeId = (String) mapIn.get("schemeId");
        Integer InsFlag = (Integer) mapIn.get("InsFlag");
        // 节点类型
        String nodeType = (String) mapIn.get("nodeType");

        Map<String, Object> qryMap = new HashMap<String, Object>();
        Map<String, Object> qryOut = new HashMap<String, Object>();
        // step1: 查询当前方案版本
        qryMap.put("schemeId", schemeId);
        // 是否获取内容详情
        qryMap.put("isGetData", "Y");
        qryOut = this.querySchemeAndVersion(qryMap);
        if (MapUtils.isEmpty(qryOut)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_NOT_EXISTS, "查询临床路径方案记录不存在，请核实配置信息！"));
        }
        CpSchemeVersion cpsv = (CpSchemeVersion) qryOut.get("cpSchemeVersion");

        // step2: 判断方案版本内容详情是否需要刷新缓存（详情为空或cacheFlag=Y都需要更新）
        Map<String, Object> outMap = new HashMap<String, Object>();
        List<Object> stageList = null;
        qryMap.clear();
        String schemeData = cpsv.getSchemeData();
        Boolean isCacheUpdate = false;
        if ("Y".equals(cpsv.getCacheFlag()) || StringUtils.isBlank(schemeData)) {
            isCacheUpdate = true;
        } else if (StringUtils.isNotBlank(schemeData)) {
            stageList = this.parseSchemeVerData(schemeData);
        }
        if (isCacheUpdate) {
            // step3: 查询方案-阶段-节点-任务-任务内容等配置
            qryMap.put("schemeVersionId", cpsv.getId());
            qryMap.put("nodeType", nodeType);
            // 不关联角色
            Map<String, Object> listOut = this.listSchemeVerData(qryMap);
            stageList = ToolUtil.typeCast(listOut.get("stageList"));

            // step4: 更新入库，保证模板内容详情最新
            if (CollectionUtils.isNotEmpty(stageList)) {
                JSONObject jsonData = new JSONObject(listOut);
                qryMap.clear();
                qryMap.put("id", cpsv.getId());
                qryMap.put("schemeData", jsonData.toJSONString());
                qryMap.put("cacheFlag", "N");
                qryMap.put("updateTime", mapIn.get("updateTime"));
                qryMap.put("updateAccept", mapIn.get("updateAccept"));
                qryMap.put("updateAuthor", mapIn.get("updateAuthor"));
                int icnt = cpSchemeDao.updateCpSchemeVersionData(qryMap);
                if (0 == icnt) {
                    throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_NOT_EXISTS, "查询临床路径方案记录不存在，请核实配置信息！"));
                }
                stageList = jsonData.getJSONArray("stageList");
            }
        }
        cpsv.setSchemeData(null);
        outMap.put("CpScheme", qryOut.get("cpScheme"));
        outMap.put("CpSchemeVersion", cpsv);

        // step5: 只取需要的阶段-节点-任务-任务内容信息
        if (CollectionUtils.isEmpty(stageList)) {
            throw (new AppException(ErrorCode.CPQUEUE_EXCEPTION_CPSCHEME_STAGE_NOT_EXISTS, "临床路径方案下阶段信息不存在，请核实配置信息！"));
        }
        List<Object> stageListNew = new ArrayList<Object>();
        if (null != InsFlag) {
            if (ConstantParams.CP_SCHEME_INS_FLAG_0 == InsFlag) {
                // 只查询建档阶段下节点
                stageListNew.add(stageList.get(0));
            } else if (ConstantParams.CP_SCHEME_INS_FLAG_1 == InsFlag) {
                // 查询建档阶段下节点以外的其他所有节点
                stageList.remove(0);
                stageListNew = stageList;
            } else if (ConstantParams.CP_SCHEME_INS_FLAG_2 == InsFlag) {
                // 查询所有节点
                stageListNew = stageList;
            }
        }
        outMap.put("stageList", stageListNew);
        logger.debug("out dealSchemeStageNode==" + outMap);

        return outMap;
    }

    /**
     * @name: 格式化临床路径内容详情
     * @author: DemonLee
     * @createTime: 2018.6.25
     * @description:
     * @modify:
     *
     */
    public List<Object> parseSchemeVerData(String templDataStr) throws Exception {
        List<Object> stageList = null;
        try {
            Map<String, Object> dataMap = JSONObject.parseObject(templDataStr);
            stageList = ToolUtil.typeCast(dataMap.get("stageList"));
        } catch (JSONException arex) {
            logger.error("临床路径内容模板格式配置错误，非json数组格式： " + arex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_CONFIG_IRREGULAR,
                    "临床路径内容模板格式配置错误，请联系系统管理员！"));
        } catch (Exception ex) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLDATA_CONFIG_IRREGULAR,
                    "问卷模板格式解析错误：" + ex.getMessage());
        }

        return stageList;
    }

    /**
     * @name: 查询临床路径配置内容（阶段-节点-任务-任务内容）
     * @author: DemonLee
     * @createTime: 2018.6.25
     * @description:
     * @modify:
     *
     */
    public Map<String, Object> listSchemeVerData(Map<String, Object> argMap) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);
        String schemeVersionId = (String) mapIn.get("schemeVersionId");
        // 节点类型
        String nodeType = (String) mapIn.get("nodeType");

        // step1: 查询路径阶段
        Map<String, Object> qryMap = new HashMap<String, Object>();
        qryMap.put("schemeVersionId", schemeVersionId);
        qryMap.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        List<CpSchemeStage> cpssList = cpSchemeStageDao.listSchemeStageByCondition(qryMap);
        if (CollectionUtils.isEmpty(cpssList)) {
            return null;
        }

        // step2: 查询每个阶段下的节点
        Map<String, Object> tmpOut = null;
        Map<String, Object> tmpIn = new HashMap<String, Object>();
        Map<String, Object> contIn = new HashMap<String, Object>();
        contIn.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        contIn.put("schemeVersionId", schemeVersionId);
        Map<String, Object> taskIn = new HashMap<String, Object>();
        taskIn.put("schemeVersionId", schemeVersionId);
        taskIn.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        List<Object> stageList = new ArrayList<Object>();
        qryMap.put("nodeType", nodeType);
        CpSchemeStage cpssVo = null;
        int c = 0;
        int csize = cpssList.size();
        for (c = 0; c < csize; c++) {
            Map<String, Object> stageMap = new HashMap<String, Object>();
            List<Object> cpNodeList = new ArrayList<Object>();
            stageMap.put("nodeList", cpNodeList);
            cpssVo = cpssList.get(c);
            stageMap.put("stageInfo", cpssVo);

            qryMap.put("stageId", cpssVo.getId());
            // 可能返回为空
            List<CpSchemeNode> cpnList = cpSchemeNodeDao.listCpSchemeNodeByCondition(qryMap);

            // step3: 查询每个节点关联的角色及下面的任务
            if (CollectionUtils.isNotEmpty(cpnList)) {
                for (CpSchemeNode cpNode : cpnList) {
                    Map<String, Object> nodeMap = new HashMap<String, Object>();
                    List<Object> cpTaskList = new ArrayList<Object>();
                    cpNodeList.add(nodeMap);
                    nodeMap.put("nodeInfo", cpNode);
                    nodeMap.put("nodeTaskList", cpTaskList);
                    // 先查询节点下关联的角色
                    taskIn.put("nodeId", cpNode.getId());
                    List<CpNodeAuth> cpNodeAuthList = cpSchemeNodeDao.listCpNodeAuthByCondition(taskIn);
                    nodeMap.put("cpNodeAuthList", cpNodeAuthList);

                    // 再查询节点下的任务
                    List<CpNodeTask> nodeTaskList = this.listCpSchemeNodeTask(taskIn);
                    if (CollectionUtils.isNotEmpty(nodeTaskList)) {
                        for (CpNodeTask cpTask : nodeTaskList) {
                            Map<String, Object> taskMap = new HashMap<String, Object>();
                            List<Object> cpTaskContList = new ArrayList<Object>();
                            cpTaskList.add(taskMap);
                            taskMap.put("taskInfo", cpTask);
                            taskMap.put("cpTaskContList", cpTaskContList);

                            // step4: 查询每个任务下的任务内容及任务关联的角色
                            contIn.put("taskId", cpTask.getId());
                            // 先查任务关联的角色
                            List<CpNodeTaskAuth> taskAuthList = cpNodeTaskDao.listCpNodeTaskAuthByCondition(contIn);
                            taskMap.put("cpTaskAuthList", taskAuthList);
                            taskMap.put("cpTaskContList", cpTaskContList);
                            // 再查任务下的内容
                            List<CpNodeTaskCont> cntcList = cpTaskContDao.listCpTaskContByCondition(contIn);
                            if (CollectionUtils.isNotEmpty(cntcList)) {
                                for (CpNodeTaskCont cpTaskCont : cntcList) {
                                    // step5: 查询内容模板信息
                                    tmpIn.put("tmplId", cpTaskCont.getTemplId());
                                    tmpIn.put("templVersion", cpTaskCont.getTemplVersion());
                                    tmpOut = this.dealContTemplInfo(tmpIn);
                                    if (MapUtils.isEmpty(tmpOut)) {
                                        continue;
                                    }

                                    Map<String, Object> contMap = new HashMap<String, Object>();
                                    cpTaskContList.add(contMap);
                                    contMap.put("contInfo", cpTaskCont);
                                    contMap.put("templType", tmpOut.get("templType"));
                                    contMap.put("templVersionId", tmpOut.get("templVersionId"));
                                }
                            }
                        }
                    }
                }
            }
            stageList.add(stageMap);
        }

        outMap.put("stageList", stageList);

        return outMap;
    }

    /**
     * @name: 任务内容模板查询及缓存处理
     * @author: DemonLee
     * @createTime: 2018.4.28
     * @param: 内容模板id等
     * @return: map
     * @modify:
     */
    @Override
    public Map<String, Object> dealContTemplInfo(Map<String, Object> mapIn) throws Exception {
        Map<String, Object> outMap = new HashMap<String, Object>();
        Map<String, Object> qryMap = new HashMap<String, Object>();
        String tmplId = (String) mapIn.get("tmplId");
        Integer templVersion = (Integer) mapIn.get("templVersion");

        // step1: 先从内存查，没有再从数据库查（后续把redis缓存加上）
        ConfCacheUtil confCache = ConfCacheUtil.getInstance();
        String templType = (String) confCache
                .getContTemplInfo(ConstantParams.CONF_CACHE_TYPE + Constants.UNDER_LINE_SPLIT_STR + tmplId);
        String templVersionId = (String) confCache.getContTemplInfo(ConstantParams.CONF_CACHE_VERSION
                + Constants.UNDER_LINE_SPLIT_STR + tmplId + Constants.UNDER_LINE_SPLIT_STR + templVersion);
        if (StringUtils.isBlank(templType) || StringUtils.isBlank(templVersionId)) {
            qryMap.put("tmplId", tmplId);
            qryMap.put("templVersion", templVersion);
            Map<String, Object> qryOut = contTemplService.queryContTemplNoText(qryMap);
            if (MapUtils.isEmpty(qryOut)) {
                return null;
            } else {
                ContentTempl contTempl = (ContentTempl) qryOut.get("ContentTempl");
                ContentTemplVersion contTemplVer = (ContentTemplVersion) qryOut.get("ContentTemplVersion");
                templType = contTempl.getTemplType();
                templVersionId = contTemplVer.getId();
                outMap.put("templType", templType);
                outMap.put("templVersionId", templVersionId);

                // step2: 向缓存里保存数据
                confCache.setContTemplInfo(ConstantParams.CONF_CACHE_TYPE + Constants.UNDER_LINE_SPLIT_STR + tmplId,
                        templType);
                confCache.setContTemplInfo(ConstantParams.CONF_CACHE_VERSION + Constants.UNDER_LINE_SPLIT_STR + tmplId
                        + Constants.UNDER_LINE_SPLIT_STR + templVersion, templVersionId);
            }
        } else {
            outMap.put("templType", templType);
            outMap.put("templVersionId", templVersionId);
        }

        return outMap;
    }

	/* (non-Javadoc)
	 * @see com.bbcare.cp.plat.service.ICpSchemeTemplService#qrySchemeVersionByid(java.lang.String)
	 */
	@Override
	public CpSchemeVersion qrySchemeVersionById(String id) throws Exception {
		Map<String,Object> qryMap = new HashMap<String,Object>();
		qryMap.put("id",id);
		List<CpSchemeVersion> list = cpSchemeDao.listCpSchemeVersionDataById(qryMap);
		if(!CollectionUtils.isEmpty(list)){
			return list.get(0);
		}
		return null;
	}
}
